package com.zhuqi.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import com.alibaba.excel.EasyExcel;
import com.zhuqi.configuration.ExecutorConfiguration;
import com.zhuqi.configuration.FilePathList;
import com.zhuqi.domain.ExportExcel;
import com.zhuqi.service.AbstractCalcInterfaceCount;
import com.zhuqi.service.CalcInterfaceCount;
import com.zhuqi.service.FileReader;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.LongAdder;

/**
 * @author : ZhuQi
 * @version : 时间:2022/8/9 13:39 版本:
 */
@Service
@Slf4j
public class FileReaderImpl implements FileReader {

    @Autowired
    private FilePathList filePathList;

    @Autowired
    private CalcInterfaceCount calcInterfaceCount;

    @Qualifier("taskExecutor")
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;

    @Autowired
    private ExecutorConfiguration executorConfiguration;

    /**
     * 导出的表格名称
     */
    private final String EXPORT_FILE_NAME = "./interfaceCount.xlsx";


    /**
     * 文件读取
     */
    @Override
    @SneakyThrows
    public void readFiles() {
        TimeInterval timer = DateUtil.timer();
        timer.start();
        ArrayList<String> list = filePathList.getList();
        ThreadPoolExecutor threadPoolExecutor = taskExecutor.getThreadPoolExecutor();

        CountDownLatch countDownLatch = new CountDownLatch(list.size());
        for (String path : list) {
            calcInterfaceCount.doRead(path, countDownLatch);
            BlockingQueue<Runnable> queue = threadPoolExecutor.getQueue();
            if (queue.size() > 500) {
                try {
                    TimeUnit.MILLISECONDS.sleep(200L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        while (true) {
            if (countDownLatch.getCount() == 0) {
                // 输出数据
                writerData(AbstractCalcInterfaceCount.getMap());
                long l = timer.intervalSecond();
                log.info("执行时长:{}秒 ", l);
                threadPoolExecutor.shutdown();
                break;
            } else {
                BlockingQueue<Runnable> queue = threadPoolExecutor.getQueue();
                if (queue.size() < 50) {
                    for (int i = 0; i < 50; i++) {
                        Runnable work = executorConfiguration.getBlockingQueue().poll();
                        if (!ObjectUtils.isEmpty(work)) {
                            threadPoolExecutor.execute(work);
                        }
                        if (threadPoolExecutor.getQueue().size() > 500) {
                            break;
                        }
                    }
                }
                TimeUnit.SECONDS.sleep(1L);
            }
        }
    }

    /**
     * 输出数据
     *
     * @param map URI map
     */
    private void writerData(HashMap<String, LongAdder> map) {
        log.info("任务执行完成，开始输出数据--------");
        ArrayList<ExportExcel> exportExcels = new ArrayList<>();
        Set<String> keys = map.keySet();
        for (String key : keys) {
            ExportExcel data = new ExportExcel();
            data.setURI(key);
            data.setCount(map.get(key).sum());
            exportExcels.add(data);
        }
        try {
            EasyExcel.write(EXPORT_FILE_NAME, ExportExcel.class).sheet().doWrite(exportExcels);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}
